"""
@description 网络优化和安全检测模块
"""
import subprocess
import platform
import socket
import psutil
import winreg
import os
import sys
import logging
import ctypes
from typing import Dict, List, Union, Tuple
from datetime import datetime
import re

class NetworkOptimizer:
    """
    @description 网络优化类
    """
    
    @staticmethod
    def optimize_network() -> Dict:
        """
        @description 执行网络优化
        @returns {Dict} 优化结果
        """
        results = {
            "status": True,
            "optimizations": {},
            "message": "网络优化完成"
        }
        
        # DNS缓存优化
        dns_result = NetworkOptimizer.flush_dns()
        results["optimizations"]["dns"] = dns_result
        
        # TCP/IP 优化
        tcp_result = NetworkOptimizer.optimize_tcp_params()
        results["optimizations"]["tcp"] = tcp_result
        
        # 网络适配器优化
        adapter_result = NetworkOptimizer.optimize_network_adapters()
        results["optimizations"]["adapter"] = adapter_result
        
        return results

    @staticmethod
    def flush_dns() -> Dict:
        """
        @description 刷新DNS缓存
        @returns {Dict} 操作结果
        """
        try:
            subprocess.run(['ipconfig', '/flushdns'], 
                         capture_output=True, 
                         check=True)
            return {
                "status": True,
                "message": "DNS缓存已清理"
            }
        except Exception as e:
            return {
                "status": False,
                "message": f"DNS缓存清理失败: {str(e)}"
            }

    @staticmethod
    def optimize_tcp_params() -> Dict:
        """
        @description 优化TCP参数
        @returns {Dict} 优化结果
        """
        try:
            if platform.system().lower() != 'windows':
                return {"status": False, "message": "仅支持Windows系统"}

            # 优化TCP参数的命令列表
            commands = [
                'netsh int tcp set global autotuninglevel=normal',
                'netsh int tcp set global chimney=enabled',
                'netsh int tcp set global dca=enabled',
                'netsh int tcp set global netdma=enabled',
                'netsh int tcp set global ecncapability=enabled'
            ]

            results = []
            for cmd in commands:
                try:
                    subprocess.run(cmd.split(), 
                                 capture_output=True, 
                                 check=True)
                    results.append(f"成功: {cmd}")
                except:
                    results.append(f"失败: {cmd}")

            return {
                "status": True,
                "data": results,
                "message": "TCP参数优化完成"
            }
        except Exception as e:
            return {
                "status": False,
                "message": f"TCP参数优化失败: {str(e)}"
            }

    @staticmethod
    def is_admin() -> bool:
        """
        @description 检查是否具有管理员权限
        @returns {bool} 是否具有管理员权限
        """
        try:
            return ctypes.windll.shell32.IsUserAnAdmin()
        except:
            return False

    @staticmethod
    def run_as_admin(cmd: str, shell: bool = True) -> Tuple[bool, str]:
        """
        @description 以管理员权限运行命令
        @param {str} cmd - 要执行的命令
        @param {bool} shell - 是否使用shell执行
        @returns {Tuple[bool, str]} (是否成功, 结果消息)
        """
        try:
            if not NetworkOptimizer.is_admin():
                if platform.system().lower() == 'windows':
                    # 如果不是管理员，尝试请求权限
                    ctypes.windll.shell32.ShellExecuteW(
                        None, "runas", sys.executable, " ".join(sys.argv), None, 1
                    )
                    return False, "需要管理员权限，请在新窗口中继续操作"
            
            # 使用 runas 命令执行
            powershell_cmd = f'powershell -Command "Start-Process powershell -ArgumentList \'-NoProfile -ExecutionPolicy Bypass -Command {cmd}\' -Verb RunAs"'
            result = subprocess.run(powershell_cmd, shell=True, capture_output=True, text=True)
            
            if result.returncode == 0:
                return True, "命令执行成功"
            else:
                return False, f"命令执行失败: {result.stderr}"
        except Exception as e:
            return False, f"执行出错: {str(e)}"

    @staticmethod
    def optimize_network_adapters() -> Dict:
        """
        @description 优化网络适配器设置
        @returns {Dict} 优化结果
        """
        if not NetworkOptimizer.is_admin():
            return {
                "status": False,
                "message": "需要管理员权限才能执行网络优化"
            }

        try:
            # 获取活动的网络适配器
            active_adapters = []
            for nic in psutil.net_if_stats().items():
                if nic[1].isup:
                    active_adapters.append(nic[0])

            results = []
            for adapter in active_adapters:
                try:
                    # 使用管理员权限执行命令
                    cmd = f'Get-NetAdapter -Name "{adapter}" | Set-NetIPInterface -AutomaticMetric Enabled'
                    success, message = NetworkOptimizer.run_as_admin(cmd)
                    
                    if success:
                        results.append(f"已优化适配器: {adapter}")
                    else:
                        results.append(f"优化失败 ({adapter}): {message}")

                    # 对物理适配器进行额外优化
                    if "Loopback" not in adapter and "Virtual" not in adapter:
                        cmd = f'Get-NetAdapter -Name "{adapter}" | Set-NetAdapterAdvancedProperty -DisplayName "Energy Efficient Ethernet" -DisplayValue "Disabled" -ErrorAction SilentlyContinue'
                        NetworkOptimizer.run_as_admin(cmd)
                except Exception as e:
                    results.append(f"优化失败 ({adapter}): {str(e)}")

            # 应用全局网络优化
            try:
                cmds = [
                    'Set-NetTCPSetting -SettingName InternetCustom -AutoTuningLevelLocal Normal',
                    'Set-NetOffloadGlobalSetting -ReceiveSegmentCoalescing Enabled',
                    'Set-NetOffloadGlobalSetting -ChimneyOffload Enabled'
                ]
                
                for cmd in cmds:
                    success, message = NetworkOptimizer.run_as_admin(cmd)
                    if success:
                        results.append("已应用全局网络优化设置")
                    else:
                        results.append(f"全局优化设置失败: {message}")
            except Exception as e:
                results.append(f"全局优化设置失败: {str(e)}")

            return {
                "status": True,
                "data": results,
                "message": "网络适配器优化完成"
            }
        except Exception as e:
            return {
                "status": False,
                "message": f"网络适配器优化失败: {str(e)}"
            }

    @staticmethod
    def get_default_gateway() -> str:
        """
        @description 获取默认网关地址
        @returns {str} 网关IP地址
        """
        try:
            if platform.system().lower() == 'windows':
                # 方法1：使用 wmic
                try:
                    cmd = 'wmic nicconfig where "IPEnabled=True" get DefaultIPGateway /format:list'
                    output = subprocess.check_output(cmd, shell=True, text=True, encoding='gbk')
                    for line in output.split('\n'):
                        if 'DefaultIPGateway=' in line:
                            gateway = line.split('=')[1].strip().strip('{}[]"\'')
                            if gateway and gateway != '0.0.0.0':
                                return gateway
                except Exception as e:
                    logging.error(f"WMIC方法获取网关失败: {str(e)}")

                # 方法2：使用 PowerShell
                try:
                    cmd = 'powershell -Command "Get-NetRoute -DestinationPrefix \'0.0.0.0/0\' | Select-Object -ExpandProperty NextHop"'
                    output = subprocess.check_output(cmd, shell=True, text=True, encoding='gbk')
                    gateway = output.strip()
                    if gateway and gateway != '0.0.0.0':
                        return gateway
                except Exception as e:
                    logging.error(f"PowerShell方法获取网关失败: {str(e)}")

                # 方法3：使用 netstat
                try:
                    cmd = 'netstat -rn | findstr "0.0.0.0.*0.0.0.0"'
                    output = subprocess.check_output(cmd, shell=True, text=True, encoding='gbk')
                    for line in output.split('\n'):
                        parts = [p for p in line.split() if p.strip()]
                        if len(parts) >= 2:
                            gateway = parts[2].strip()
                            if gateway and gateway != '0.0.0.0':
                                return gateway
                except Exception as e:
                    logging.error(f"Netstat方法获取网关失败: {str(e)}")

            return None
        except Exception as e:
            logging.error(f"获取默认网关失败: {str(e)}")
            return None

    @staticmethod
    def check_gateway_connectivity() -> Dict:
        """
        @description 检查网关连通性
        @returns {Dict} 检查结果
        """
        try:
            gateway = NetworkOptimizer.get_default_gateway()
            if not gateway:
                return {
                    "status": False,
                    "message": "无法获取默认网关地址"
                }

            # 验证网关地址格式
            ip_pattern = r'^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$'
            if not re.match(ip_pattern, gateway):
                return {
                    "status": False,
                    "message": f"获取到的网关地址格式无效: {gateway}"
                }

            logging.info(f"正在测试网关连通性: {gateway}")

            # 使用 PowerShell 的 Test-Connection 命令
            try:
                cmd = f'powershell -Command "Test-Connection -ComputerName {gateway} -Count 4 -Quiet"'
                result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
                
                if "True" in result.stdout:
                    # 获取详细的延迟信息
                    cmd_detail = f'powershell -Command "$ping = Test-Connection -ComputerName {gateway} -Count 4; $ping | Measure-Object -Property ResponseTime -Average | Select-Object -ExpandProperty Average"'
                    detail_result = subprocess.run(cmd_detail, shell=True, capture_output=True, text=True)
                    
                    try:
                        avg_time = float(detail_result.stdout.strip())
                        return {
                            "status": True,
                            "data": {
                                "gateway": gateway,
                                "avg_time": avg_time
                            },
                            "message": f"网关可访问，平均响应时间: {avg_time:.2f}ms"
                        }
                    except:
                        return {
                            "status": True,
                            "data": {
                                "gateway": gateway,
                                "avg_time": None
                            },
                            "message": "网关可访问"
                        }
                else:
                    return {
                        "status": False,
                        "data": {"gateway": gateway},
                        "message": f"无法连接到网关 {gateway}"
                    }
            except Exception as e:
                logging.error(f"PowerShell测试连接失败: {str(e)}")
                
                # 如果PowerShell方法失败，尝试使用传统ping命令
                try:
                    subprocess.run(['ping', '-n', '1', '-w', '1000', gateway], 
                                 check=True, capture_output=True)
                    return {
                        "status": True,
                        "data": {
                            "gateway": gateway,
                            "avg_time": None
                        },
                        "message": "网关可访问"
                    }
                except subprocess.CalledProcessError:
                    return {
                        "status": False,
                        "data": {"gateway": gateway},
                        "message": f"无法连接到网关 {gateway}"
                    }
            
        except Exception as e:
            logging.error(f"网关连通性测试失败: {str(e)}")
            return {
                "status": False,
                "message": f"网关连通性测试失败: {str(e)}"
            }

    @staticmethod
    def diagnose_network() -> Dict:
        """
        @description 全面的网络诊断
        @returns {Dict} 诊断结果
        """
        results = {
            "status": True,
            "tests": {},
            "message": "诊断完成"
        }

        # DNS解析测试
        dns_result = NetworkOptimizer.test_dns_resolution()
        results["tests"]["dns"] = dns_result

        # 网关连通性测试
        gateway_result = NetworkOptimizer.check_gateway_connectivity()
        results["tests"]["gateway"] = gateway_result

        # 公网连通性测试
        internet_result = NetworkOptimizer.check_internet_connection()
        results["tests"]["internet"] = internet_result

        # 常见端口测试
        port_result = NetworkOptimizer.test_common_ports()
        results["tests"]["ports"] = port_result

        return results

class NetworkRepair:
    """
    @description 网络修复类
    """
    
    @staticmethod
    def repair_network(diagnosis_result: Dict) -> Dict:
        """
        @description 根据诊断结果进行网络修复
        @param {Dict} diagnosis_result - 诊断结果
        @returns {Dict} 修复结果
        """
        if not NetworkOptimizer.is_admin():
            return {
                "status": False,
                "message": "需要管理员权限才能执行网络修复"
            }

        repair_results = {
            "status": True,
            "repairs": {},
            "message": "修复完成"
        }

        tests = diagnosis_result.get("tests", {})
        
        # DNS修复
        if not tests.get("dns", {}).get("status", True):
            dns_repair = NetworkRepair.repair_dns()
            repair_results["repairs"]["dns"] = dns_repair

        # 网关连接修复
        if not tests.get("gateway", {}).get("status", True):
            gateway_repair = NetworkRepair.repair_gateway_connection()
            repair_results["repairs"]["gateway"] = gateway_repair

        # 网络连接修复
        if not tests.get("internet", {}).get("status", True):
            connection_repair = NetworkRepair.repair_internet_connection()
            repair_results["repairs"]["internet"] = connection_repair

        # 端口问题修复
        if not tests.get("ports", {}).get("status", True):
            port_repair = NetworkRepair.repair_port_issues()
            repair_results["repairs"]["ports"] = port_repair

        return repair_results

    @staticmethod
    def repair_dns() -> Dict:
        """
        @description DNS问题修复
        @returns {Dict} 修复结果
        """
        try:
            repairs_made = []
            
            # 1. 刷新DNS缓存
            success, message = NetworkOptimizer.run_as_admin('ipconfig /flushdns')
            if success:
                repairs_made.append("已刷新DNS缓存")
            
            # 2. 重置DNS服务器设置
            cmd = 'Get-NetAdapter | Set-DnsClientServerAddress -ResetServerAddresses'
            success, message = NetworkOptimizer.run_as_admin(cmd)
            if success:
                repairs_made.append("已重置DNS服务器设置")
            
            # 3. 注册DNS
            success, message = NetworkOptimizer.run_as_admin('ipconfig /registerdns')
            if success:
                repairs_made.append("已注册DNS")

            return {
                "status": True,
                "repairs": repairs_made,
                "message": "DNS修复完成"
            }
        except Exception as e:
            return {
                "status": False,
                "message": f"DNS修复失败: {str(e)}"
            }

    @staticmethod
    def repair_gateway_connection() -> Dict:
        """
        @description 网关连接修复
        @returns {Dict} 修复结果
        """
        try:
            repairs_made = []
            
            # 1. 重置网络适配器
            cmd = 'Get-NetAdapter | Restart-NetAdapter'
            success, message = NetworkOptimizer.run_as_admin(cmd)
            if success:
                repairs_made.append("已重置网络适配器")
            
            # 2. 重新获取IP地址
            success, message = NetworkOptimizer.run_as_admin('ipconfig /release')
            success, message = NetworkOptimizer.run_as_admin('ipconfig /renew')
            if success:
                repairs_made.append("已重新获取IP地址")
            
            # 3. 重置TCP/IP协议栈
            success, message = NetworkOptimizer.run_as_admin('netsh int ip reset')
            if success:
                repairs_made.append("已重置TCP/IP协议栈")

            return {
                "status": True,
                "repairs": repairs_made,
                "message": "网关连接修复完成"
            }
        except Exception as e:
            return {
                "status": False,
                "message": f"网关连接修复失败: {str(e)}"
            }

    @staticmethod
    def repair_internet_connection() -> Dict:
        """
        @description 互联网连接修复
        @returns {Dict} 修复结果
        """
        try:
            repairs_made = []
            
            # 1. 重置Winsock
            success, message = NetworkOptimizer.run_as_admin('netsh winsock reset')
            if success:
                repairs_made.append("已重置Winsock")
            
            # 2. 重置代理设置
            success, message = NetworkOptimizer.run_as_admin('netsh winhttp reset proxy')
            if success:
                repairs_made.append("已重置代理设置")
            
            # 3. 清理路由表
            success, message = NetworkOptimizer.run_as_admin('route -f')
            if success:
                repairs_made.append("已清理路由表")
            
            # 4. 重置防火墙规则
            success, message = NetworkOptimizer.run_as_admin('netsh advfirewall reset')
            if success:
                repairs_made.append("已重置防火墙规则")

            return {
                "status": True,
                "repairs": repairs_made,
                "message": "网络连接修复完成"
            }
        except Exception as e:
            return {
                "status": False,
                "message": f"网络连接修复失败: {str(e)}"
            }

    @staticmethod
    def repair_port_issues() -> Dict:
        """
        @description 端口问题修复
        @returns {Dict} 修复结果
        """
        try:
            repairs_made = []
            
            # 1. 重置TCP/IP端口
            success, message = NetworkOptimizer.run_as_admin('netsh int ipv4 reset')
            if success:
                repairs_made.append("已重置IPv4端口")
            
            success, message = NetworkOptimizer.run_as_admin('netsh int ipv6 reset')
            if success:
                repairs_made.append("已重置IPv6端口")
            
            # 2. 清理端口排除
            cmd = 'netsh int ipv4 delete excludedportrange protocol=tcp'
            success, message = NetworkOptimizer.run_as_admin(cmd)
            if success:
                repairs_made.append("已清理端口排除规则")
            
            # 3. 重置Windows Socket
            success, message = NetworkOptimizer.run_as_admin('netsh winsock reset catalog')
            if success:
                repairs_made.append("已重置Windows Socket")

            return {
                "status": True,
                "repairs": repairs_made,
                "message": "端口问题修复完成"
            }
        except Exception as e:
            return {
                "status": False,
                "message": f"端口问题修复失败: {str(e)}"
            }

class SecurityChecker:
    """
    @description 安全检测类
    """
    
    @staticmethod
    def check_security() -> Dict:
        """
        @description 执行安全检查
        @returns {Dict} 检查结果
        """
        results = {
            "status": True,
            "checks": {},
            "message": "安全检查完成"
        }
        
        # 检查开放端口
        port_result = SecurityChecker.check_open_ports()
        results["checks"]["ports"] = port_result
        
        # 检查防火墙状态
        firewall_result = SecurityChecker.check_firewall()
        results["checks"]["firewall"] = firewall_result
        
        # 检查活动连接
        connection_result = SecurityChecker.check_active_connections()
        results["checks"]["connections"] = connection_result
        
        return results

    @staticmethod
    def check_open_ports(start_port: int = 1, end_port: int = 1024) -> Dict:
        """
        @description 检查开放端口
        @param {int} start_port - 起始端口
        @param {int} end_port - 结束端口
        @returns {Dict} 检查结果
        """
        try:
            open_ports = []
            for port in range(start_port, end_port + 1):
                sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                sock.settimeout(0.1)
                result = sock.connect_ex(('127.0.0.1', port))
                if result == 0:
                    open_ports.append(port)
                sock.close()

            return {
                "status": True,
                "data": open_ports,
                "message": f"发现 {len(open_ports)} 个开放端口"
            }
        except Exception as e:
            return {
                "status": False,
                "message": f"端口检查失败: {str(e)}"
            }

    @staticmethod
    def check_firewall() -> Dict:
        """
        @description 检查防火墙状态
        @returns {Dict} 检查结果
        """
        try:
            cmd = 'netsh advfirewall show allprofiles'
            result = subprocess.run(cmd.split(), 
                                  capture_output=True, 
                                  text=True)
            
            profiles = {
                'Domain Profile': False,
                'Private Profile': False,
                'Public Profile': False
            }
            
            for line in result.stdout.split('\n'):
                for profile in profiles.keys():
                    if profile in line and 'State' in line:
                        profiles[profile] = 'ON' in line.upper()

            return {
                "status": True,
                "data": profiles,
                "message": "防火墙状态检查完成"
            }
        except Exception as e:
            return {
                "status": False,
                "message": f"防火墙检查失败: {str(e)}"
            }

    @staticmethod
    def check_active_connections() -> Dict:
        """
        @description 检查活动网络连接
        @returns {Dict} 检查结果
        """
        try:
            connections = []
            for conn in psutil.net_connections(kind='inet'):
                if conn.status == 'ESTABLISHED':
                    try:
                        process = psutil.Process(conn.pid)
                        connections.append({
                            'local_address': f"{conn.laddr.ip}:{conn.laddr.port}",
                            'remote_address': f"{conn.raddr.ip}:{conn.raddr.port}",
                            'status': conn.status,
                            'pid': conn.pid,
                            'process_name': process.name()
                        })
                    except (psutil.NoSuchProcess, psutil.AccessDenied):
                        continue

            return {
                "status": True,
                "data": connections,
                "message": f"发现 {len(connections)} 个活动连接"
            }
        except Exception as e:
            return {
                "status": False,
                "message": f"连接检查失败: {str(e)}"
            } 